{.hint[XDeclaredButNotUsed]:off.}

import macros
import logging
import strutils
import asyncdispatch
import times

proc `$`*(x: pointer):string = return strutils.strip(repr(x))
proc `$`*(x: AsyncFD):string = return strutils.strip(repr(x))
proc tostr*(x: pointer):string = return strutils.strip(repr(x))
proc tostr*(x: AsyncFD):string = return strutils.strip(repr(x))


### logging initilize
const LOGLVL_TRACE = 0
const LOGLVL_DEBUG = 1
const LOGLVL_INFO = 2
const LOGLVL_WARNING = 3
const LOGLVL_ERROR = 4
const LOGLVL_FATAL = 5

const logWithDate = 1
const logWithTime = 2
const logMicroTime = 4
const logLongFile = 8
const logShortFile = 16
var nplogflags = logWithDate or logWithTime or logMicroTime
nplogflags = logWithTime or logMicroTime

let progbtime = times.epochTime()
var logtimezone = times.local()
var logtimezonep = logtimezone.addr

# nim plus log level
var nploglevel = LOGLVL_DEBUG
proc llevel(lvl: int) =
    if lvl >= LOGLVL_TRACE and lvl <= LOGLVL_FATAL:
        nploglevel = lvl

proc getnplogtime*() : string {.gcsafe.} =
    let curts = epochTime()
    let curtm = initTime(curts.int64, ((curts - curts.int64.float)*1000000000.0).int64)

    var tz = (cast[ptr TimeZone](logtimezonep))[]
    if (nplogflags and logWithDate) > 0 and (nplogflags and logWithTime) > 0 and
       (nplogflags and logMicroTime) > 0:
        return times.format(curtm, "[yyyy-MM-dd HH:mm:ss'.'fff]", tz)
    if (nplogflags and logWithDate and logWithTime) > 0:
        return times.format(curtm, "[yyyy-MM-dd HH:mm:ss]", tz)
    if (nplogflags and logWithTime) > 0  and (nplogflags and logMicroTime) > 0:
        return times.format(curtm, "[HH:mm:ss'.'fff]", tz)
    return times.format(curtm, "[HH:mm:ss]", tz)

# donnot call in anthor macro
macro logecho(lvl : string, msgs: varargs[untyped]): untyped =
    result = nnkStmtList.newTree()
    result.add newCall("echo")
    result[0].add(newCall("getnplogtime"))
    result[0].add(newLit(" [" & $lvl & "] "))

    let lineobj = msgs.lineInfoObj()
    let sepos = lineobj.filename.rfind("/")
    let shortfname = lineobj.filename[sepos+1..lineobj.filename.len()-1]
    result[0].add(newStrLitNode(shortfname))
    result[0].add(newLit(":"))
    result[0].add(newLit(lineobj.line))

    for msg in msgs:
        result[0].add(newLit(" "))
        if msg.typeKind() == ntyPointer: result[0].add(newLit(repr(msg)))
        else: result[0].add(msg)
    #discard # 可能等于 python的pass

# can call in anthor macro
proc logecho2*(msgs: varargs[string, `$`]) =
    var tinfo = instantiationInfo()
    var s = getnplogtime()
    echo "$# [INFO ] $#:$# " % [s, tinfo.filename, $tinfo.line], msgs
    return

macro ldebug*(msgs: varargs[untyped]): untyped =
    result = quote do: logecho("DEBUG", `msgs`)
    #discard # 可能等于 python的pass

macro linfo*(msgs: varargs[untyped]): untyped =
    result = quote do: logecho("INFO ", `msgs`)
    #discard # 可能等于 python的pass

macro lerror*(msgs: varargs[untyped]): untyped =
    result = quote do: logecho("ERROR", `msgs`)
    # discard


#[
echo ("123", 456)
linfo("hehehe",123)
lerror("hehehe",456)
ldebug("hehehe有",true)
ldebug("hehehe在",false)
]#

{.push hint[XDeclaredButNotUsed]:off.}
